#include <glpk.h>

#include <iostream>
#include <sstream>
#include <vector>
#include <utility>

void c_solution(unsigned nb_distance_constraints,
		const std::vector<unsigned>& c,
		const std::vector<std::pair<unsigned, unsigned> >& not_ok,
		unsigned m,
		unsigned n)
{
  const unsigned nb_coeffs = n * (nb_distance_constraints + 1);

  glp_prob* lp;

  int ia[1 + nb_coeffs];
  int ja[1 + nb_coeffs];
  double ar[1 + nb_coeffs];

  lp = glp_create_prob();
  glp_set_prob_name(lp, "plam");
  glp_set_obj_dir(lp, GLP_MAX);
  glp_add_rows(lp, nb_distance_constraints + 1);

  { // distance constraints
    for (unsigned i = 1; i <= nb_distance_constraints; ++i)
      {
	std::cout << "assigning constraint " << i << std::endl;

	std::ostringstream oss_name;
	oss_name << "d" << i;

	glp_set_row_name(lp, i, oss_name.str().c_str());
	glp_set_row_bnds(lp, i, GLP_DB, 0, 1);
      }
  }

  { // number of warehouses
    glp_set_row_name(lp, nb_distance_constraints + 1, "nb_");
    glp_set_row_bnds(lp, nb_distance_constraints + 1, GLP_FX, m, m);
  }

  glp_add_cols(lp, n);

  { // The n warehouses of the problem
    for (unsigned i = 1; i <= n; ++i)
      {
	std::cout << "assigning col " << i << std::endl;

	std::ostringstream oss_name;
	oss_name << "x" << i;

	glp_set_col_name(lp, i, oss_name.str().c_str());
	glp_set_col_bnds(lp, i, GLP_DB, 0, 1);
	glp_set_obj_coef(lp, i, c[i]);
	glp_set_col_kind(lp, i, GLP_BV);
      }
  }

  for (unsigned i = 1; i <= nb_distance_constraints; ++i)
    {
      std::cout << "setting constraint " << i << std::endl;

      //Setting all coeffs to 0.
      for (unsigned j = 1; j <= n; ++j)
	{
	  ia[(i - 1) * n + j] = i;
	  ja[(i - 1) * n + j] = j;
	  ar[(i - 1) * n + j] = 0;
	}

      //Setting xi and xj coeffs to 1.
      ar[(i - 1) * n + not_ok[i].first] = 1;
      ar[(i - 1) * n + not_ok[i].second] = 1;
    }

  //Last line : sum (xi) = m
  for (unsigned j = 1; j <= n; ++j)
    {
      ia[(nb_distance_constraints) * n + j] = nb_distance_constraints + 1;
      ja[(nb_distance_constraints) * n + j] = j;
      ar[(nb_distance_constraints) * n + j] = 1;
    }

  for (unsigned i = 1; i <= (nb_distance_constraints + 1); ++i)
    {
      std::cout << glp_get_row_name(lp, i) << " : \t";
      for (unsigned j = 1; j <= n; ++j )
	{
	  std::cout << ar[(i - 1) * n + j] << "\t";
	}
      std::cout << "lb : " << glp_get_row_lb (lp, i) << " ub : " << glp_get_row_ub (lp, i) << " and type " << glp_get_row_type (lp, i) << std::endl;
    }

  glp_load_matrix(lp, nb_coeffs, ia, ja, ar);

  glp_simplex(lp, NULL);

  glp_intopt(lp,NULL);

  int z = glp_mip_obj_val(lp);

  std::cout << "Capacite des depots choisis = " << z << std::endl;

  for (unsigned i = 1; i <= n; ++i)
    {
      int x = glp_mip_col_val(lp, i);
      //      std::cout << "col " << i << " : x = " << x << std::endl;
      if (x == 1)
      	std::cout << "Entrepot numero " << i << " choisi" << std::endl;
    }

  glp_delete_prob(lp);
}
